package com.tinusgraglin.enclusiv.ui.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tinusgraglin.enclusiv.Util
import com.tinusgraglin.enclusiv.datalayer.*
import com.tinusgraglin.enclusiv.datalayer.repos.ArticleRepo
import com.tinusgraglin.enclusiv.datalayer.repos.UserRepo
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class MainActivityViewModel(
    private val articleRepo: ArticleRepo,
    private val userRepo: UserRepo
) : ViewModel() {
    val loggedInUserProfile by lazy {
        userRepo.cachedLoggedInUserProfile!!
    }

    private val oneShotRecommendAmount = 10
    private val oneShotEmpty = List<ShowedArticleProfile?>(oneShotRecommendAmount) {null}

    private val _recommended = MutableStateFlow(listOf<ShowedArticleProfile?>())
    val recommended = _recommended.asStateFlow()

    data class RefreshingStates(
        val recommendIsRefreshing: Boolean,
        val listenedIsRefreshing: Boolean
    )

    fun toggleRecommendedArticleUserArticleStats(i: Int, wantedStats: UserArticleStats) {
        _recommended.update {
            it.toMutableList().also { mutableIt ->
                val item = mutableIt[i]
                if (item != null) {
                    val stats = item.articleStats
                    mutableIt[i] = item.copy(userArticleStats = wantedStats, articleStats = ArticleStats(stats.viewers, stats.likes + if (wantedStats.like) 1 else 0, stats.collects + if(wantedStats.collect) 1 else 0))
                }
            }
        }
    }

    private val _refreshingState = MutableStateFlow(RefreshingStates(false, false))
    val refreshingStates = _refreshingState.asStateFlow()

    fun addMyNewlyUploadedArticle(aid: Long, article: EditedArticle) {
        val newArticle = ShowedArticleProfile(
            id = aid,
            title = article.title,
            authorName = loggedInUserProfile.name,
            authorId = loggedInUserProfile.id,
            authorProfileImgUrl = Util.toImageUrl("profile_img/image", loggedInUserProfile.id),
            contentSegments = listOf(article.content),
            contentCombined = article.content,
            imageUrls = listOf(),
            articleStats = ArticleStats(0,0,0),
            userArticleStats = UserArticleStats(false, false)
        )
        _recommended.update { l ->
            l.toMutableList().apply {
                add(0, newArticle)
            }
        }
    }

    fun fetchArticleAsync(aid: Long) : Deferred<ShowedArticleProfile> =
        Util.requestWithDeferredResultAsync(viewModelScope) {
            articleRepo.getArticle(aid)
        }

    fun getOneShotRecommended() {
        _refreshingState.update {
            it.copy(recommendIsRefreshing = true)
        }
        _recommended.value = _recommended.value.toMutableList().apply { addAll(0, oneShotEmpty) }
        viewModelScope.launch {
            val l = userRepo.getRecommended(loggedInUserProfile.id)
            l.forEachIndexed { idx, item ->
                val article = articleRepo.getArticle(item)
                val userArticleStats = userRepo.getUserArticleStats(loggedInUserProfile.id, item)
                _recommended.value = _recommended.value.toMutableList().also {
                    it[idx] = article.copy(userArticleStats = userArticleStats)
                }
            }
            _refreshingState.update {
                it.copy(recommendIsRefreshing = false)
            }
        }
    }

    fun getRecommendedAsync(): Deferred<List<Long>> =
        Util.requestWithDeferredResultAsync(viewModelScope) {
            userRepo.getRecommended(loggedInUserProfile.id)
        }

    fun getMyArticleAsync(): Deferred<List<Long>> =
        Util.requestWithDeferredResultAsync(viewModelScope) {
            userRepo.getOwnedArticle(loggedInUserProfile.id)
        }
}